package org.jeecg.jt808;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;
import org.jeecg.jt808.req.*;
import org.jeecg.jt808.util.JT808Util;
import org.jeecg.jt808.vo.JT808DataPacket;

import static org.jeecg.jt808.constant.JT808Constant.*;


/**
 * Created by houcheng when 2018/7/1.
 */
public final class JTT808Decoder
{
    public static JT808DataPacket decode(String body)
    {

        ByteBuf buf = Unpooled.copiedBuffer(hexStringToByteArray(body));
        int startIndex = buf.indexOf(0, buf.readableBytes(), (byte) 0x7E) + 1;
        int endIndex = buf.indexOf(startIndex, buf.readableBytes(), (byte) 0x7E);
        ByteBuf dataBetween7E = buf.slice(startIndex, endIndex - startIndex);

        JT808DataPacket msg=decodeByteBuf( dataBetween7E);
        return msg;
    }

    public static JT808DataPacket decodeByteBuf(ByteBuf in) {
        if (in.readableBytes() < 12) { //包头最小长度
            return null;
        }
        //转义
        byte[] raw = new byte[in.readableBytes()];
        in.readBytes(raw);
        ByteBuf escape = revert(raw);
        //校验
        byte pkgCheckSum = escape.getByte(escape.writerIndex() - 1);
        escape.writerIndex(escape.writerIndex() - 1);//排除校验码
        byte calCheckSum = JT808Util.XorSumBytes(escape);
        if (pkgCheckSum != calCheckSum) {
            //log.warn("校验码错误,pkgCheckSum:{},calCheckSum:{}", pkgCheckSum, calCheckSum);
            ReferenceCountUtil.safeRelease(escape);
            return null;
        }
        //解码
        return parse(escape);
    }

    public static JT808DataPacket parse(ByteBuf bb) {
        JT808DataPacket packet = null;
        short msgId = bb.getShort(bb.readerIndex());
        switch (msgId) {
            case TERNIMAL_MSG_HEARTBEAT:
                packet = new HeartBeatMsg(bb);
                break;
            case TERNIMAL_MSG_LOCATION:
                packet = new LocationNewMsg(bb);
                break;
            case TERNIMAL_MSG_REGISTER:
                packet = new RegisterMsg(bb);
                break;
            case TERNIMAL_MSG_AUTH:
                packet = new AuthMsg(bb);
                break;
            case TERNIMAL_MSG_LOGOUT:
                packet = new LogOutMsg(bb);
                break;
            case SERVER_RESP_REGISTER:
                packet = new JT808DataPacket(bb);
                break;
            case TERNIMAL_MSG_TRANSPARENT:
                packet = new TransparencyMsg(bb);
                break;
            case TERMINAL_ATTRIBUTE_RESPONSE_MSG:
                packet = new TerminalAttributeResponseMsg(bb);
                break;
            default:
                packet = new JT808DataPacket(bb);
                break;
        }
        packet.parse();
        return packet;
    }

    public static ByteBuf revert(byte[] raw) {
        int len = raw.length;
        ByteBuf buf = ByteBufAllocator.DEFAULT.heapBuffer(len);//DataPacket parse方法回收
        for (int i = 0; i < len; i++) {
            //这里如果最后一位是0x7d会导致index溢出，说明原始报文转义有误
            if (raw[i] == 0x7d && raw[i + 1] == 0x01) {
                buf.writeByte(0x7d);
                i++;
            } else if (raw[i] == 0x7d && raw[i + 1] == 0x02) {
                buf.writeByte(0x7e);
                i++;
            } else {
                buf.writeByte(raw[i]);
            }
        }
        return buf;
    }

    private static byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}
